# ============================================================================
# NFShmXFrame 主 Makefile
# ============================================================================
# 此Makefile整合了所有构建脚本的功能，提供统一的构建接口
# 
# 主要目标分类：
#   1. auto-make系列: 执行子模块的makefile生成代码
#   2. build系列: 完整的cmake构建流程
#   3. 工具构建: Excel处理工具等
# ============================================================================

.PHONY: help
.DEFAULT_GOAL := help

# ============================================================================
# 配置变量
# ============================================================================
BUILD_DIR := Build
BUILD_GAME_DIR := $(BUILD_DIR)/game
BUILD_LIB_DIR := $(BUILD_DIR)/Lib
BUILD_DEBUG_DIR := $(BUILD_DIR)/build64_debug
BUILD_RELEASE_DIR := $(BUILD_DIR)/build64_release
BUILD_DYNAMIC_DEBUG_DIR := $(BUILD_DIR)/build64_dynamic_debug
BUILD_DYNAMIC_RELEASE_DIR := $(BUILD_DIR)/build64_dynamic_release
BUILD_EXCELPROCESS_DIR := Build_excelprocess/build64_debug

# 构建工具选择（ninja 优先，否则使用 make）
ifeq ($(shell command -v ninja 2>/dev/null),)
  ifeq ($(shell command -v ninja-build 2>/dev/null),)
    # 没有 ninja，使用 make
    CMAKE_GENERATOR :=
    BUILD_TOOL := $(MAKE)
  else
    # 使用 ninja-build
    CMAKE_GENERATOR := -G Ninja
    BUILD_TOOL := ninja-build
  endif
else
  # 使用 ninja
  CMAKE_GENERATOR := -G Ninja
  BUILD_TOOL := ninja
endif

# 游戏项目配置
# GAME_DIR: 指定使用哪个游戏项目，默认为 LieRen
# 可通过命令行传入: make GAME_DIR=OtherGame
# 当GAME_DIR为空时，不会对game目录进行任何操作，也不会编译游戏代码
GAME_DIR ?= LieRen

# DRY_RUN 模式：仅打印命令，不执行
DRY_RUN ?= 0

# 安装配置
# INSTALL_DIR: 安装目标目录，默认为 Deploy
# BUILD_TYPE: 构建类型 (Debug/Release/DynamicDebug/DynamicRelease)，默认为 DynamicDebug
# 如果未指定 BUILD_TYPE，会根据最近构建的目录自动判断，或使用默认值 DynamicDebug
INSTALL_DIR ?= Deploy
# 展开 INSTALL_DIR 中的 ~ 为实际的 home 目录路径
# 如果 INSTALL_DIR 以 ~ 开头，则展开为 $HOME 路径
ifeq ($(shell echo "$(INSTALL_DIR)" | cut -c1),~)
  INSTALL_DIR := $(shell eval echo "$(INSTALL_DIR)")
endif
# BUILD_TYPE 将在 install 目标中自动判断或使用默认值

# 子模块makefile路径
NFCOMM_MAKEFILES := src/NFrame/NFComm/makefiles
NFSERVER_MAKEFILES := src/NFServer/NFServerComm/makefiles
GAME_MAKEFILES := game/makefiles

# 环境准备相关路径
TOOLS_DIR := tools
GOOGLE_PROTOBUF_DIR := $(TOOLS_DIR)/google3.6
GOOGLE_PROTOBUF_PYTHON_DIR := $(GOOGLE_PROTOBUF_DIR)/python
GOOGLE_PROTOBUF_SRC_DIR := $(GOOGLE_PROTOBUF_DIR)/src
PROTOC_SOURCE := $(TOOLS_DIR)/protoc

# Python版本检测（优先使用Python 2.7，回退到Python 3）
# Google Protobuf 3.6 支持 Python 2.7 和 Python 3
PYTHON_CMD := $(shell command -v python2.7 2>/dev/null || command -v python3 2>/dev/null || command -v python 2>/dev/null || echo python)

# 并行构建任务数
# 优先级：命令行参数 > 环境变量 > 默认值（CPU 核心数或 4）
# distcc 动态负载均衡会通过环境变量设置 JOBS
# 优化建议：对于 I/O 密集型编译，可以设置为 CPU 核心数的 1.5-2 倍
ifndef JOBS
  JOBS := $(shell nproc 2>/dev/null || echo 4)
  # 对于 I/O 密集型编译，可以增加并行任务数
  # 如果系统有足够内存，可以设置为 CPU 核心数的 2 倍
  # JOBS := $(shell echo $$(($(shell nproc 2>/dev/null || echo 4) * 2)))
endif

# 是否跳过makefiles代码生成步骤（默认不跳过）
# 可通过命令行传入: make build-debug SKIP_MAKEFILES=1
SKIP_MAKEFILES ?= 0

# 编译器选择（Clang vs GCC）
# USE_CLANG: 是否使用 Clang 编译器（默认: 1，Linux 上使用 Clang；设为 0 使用 GCC）
# CLANG_VERSION: Clang 版本号（默认: 14）
# 在 Linux 上默认使用 Clang（更快），Windows 上默认使用 GCC
# 注意：这些变量可以通过环境变量传递给 CMake，CMake 的 ClangConfig.cmake 会自动检测和配置编译器
USE_CLANG ?= 1
CLANG_VERSION ?= 14

# 导出环境变量，确保 CMake 的 ClangConfig.cmake 能够读取到
export USE_CLANG
export CLANG_VERSION

# 编译器检测和配置已完全由 CMake 的 ClangConfig.cmake 负责
# 不再在 Makefile 中进行编译器检测，避免重复工作

# ============================================================================
# 帮助信息
# ============================================================================
help:
	@echo "============================================================================"
	@echo "NFShmXFrame 构建系统"
	@echo "============================================================================"
	@echo ""
	@echo "环境准备:"
	@echo "  ./ci/build.sh init                            - 准备构建环境（首次使用前必须执行）"
	@echo "                                                  - 所有环境安装已统一到 ci/build.sh"
	@echo "                                                  - 不再使用 Makefile 安装环境"
	@echo ""
	@echo "代码生成目标 (auto-make系列):"
	@echo "  make auto-make [GAME_DIR=项目名]              - 动态执行子模块makefiles系统，makefiels系统会根据现有文件变动，自动将变动的部分文件(proto、Excel)转变成配置文件和代码"
	@echo "  make auto-make-all [GAME_DIR=项目名]          - 清理后,全部重新将(proto、Excel)转变成配置文件和代码"
	@echo "  make auto-make-patch [GAME_DIR=项目名]        - 发patch小版本,打补丁热更服务器时用，不允许修改后的proto,Excel生成的代码有变动，patch会比较他们与系统的原有代码是否一样，不一样返回失败，停止执行"
	@echo "  make auto-make-patch-all [GAME_DIR=项目名]    - 清理后,全部重新将(proto、Excel)转变成配置文件和代码.不允许修改后的proto,Excel生成的代码有变动，patch会比较他们与系统的原有代码是否一样，不一样返回失败，停止执行"
	@echo ""
	@echo "参数说明:"
	@echo "  GAME_DIR=项目名              - 指定游戏项目目录（默认: 空，不编译游戏）"
	@echo "                                 例如: make debug GAME_DIR=LieRen"
	@echo "                                 当GAME_DIR为空时，不会对game目录进行任何操作，也不会编译游戏代码"
	@echo "  SKIP_MAKEFILES=1             - 跳过makefiles代码生成步骤（默认: 0，不跳过）"
	@echo "                                 例如: make debug SKIP_MAKEFILES=1"
	@echo "                                 适用场景: proto和Excel文件没有变化时，加快构建速度"
	@echo "  JOBS=N                       - 并行编译任务数（默认: 4）"
	@echo "                                 例如: make debug JOBS=8"
	@echo ""
	@echo "Debug构建目标:"
	@echo "  make debug            - Debug完整构建"
	@echo "  make debug-all        - 清理后Debug完整构建"
	@echo "  make debug-patch      - Debug补丁构建（不清理cmake）"
	@echo "  make debug-patch-all  - 清理后Debug补丁构建"
	@echo ""
	@echo "DynamicDebug构建目标:"
	@echo "  make dynamic-debug            - DynamicDebug完整构建"
	@echo "  make dynamic-debug-all        - 清理后DynamicDebug完整构建"
	@echo "  make dynamic-debug-patch      - DynamicDebug补丁构建"
	@echo "  make dynamic-debug-patch-all  - 清理后DynamicDebug补丁构建"
	@echo ""
	@echo "DynamicRelease构建目标:"
	@echo "  make dynamic-release            - DynamicRelease完整构建"
	@echo "  make dynamic-release-all        - 清理后DynamicRelease完整构建"
	@echo "  make dynamic-release-patch      - DynamicRelease补丁构建"
	@echo "  make dynamic-release-patch-all  - 清理后DynamicRelease补丁构建"
	@echo ""
	@echo "Release构建目标:"
	@echo "  make release            - Release完整构建"
	@echo "  make release-all        - 清理后Release完整构建"
	@echo "  make release-patch      - Release补丁构建"
	@echo "  make release-patch-all  - 清理后Release补丁构建"
	@echo ""
	@echo "工具构建目标:"
	@echo "  make excelprocess     - 构建Excel处理工具"
	@echo ""
	@echo "部署目标:"
	@echo "  便捷安装（推荐，先编译后安装，GAME_DIR 默认为 LieRen）:"
	@echo "    make install-debug            - Debug 构建并安装"
	@echo "    make install-release          - Release 构建并安装"
	@echo "    make install-dynamic-debug    - DynamicDebug 构建并安装"
	@echo "    make install-dynamic-release - DynamicRelease 构建并安装"
	@echo "    示例: make install-debug GAME_DIR=OtherGame INSTALL_DIR=/opt/game"
	@echo ""
	@echo "  通用安装（自动检测或指定 BUILD_TYPE）:"
	@echo "    make install GAME_DIR=项目名  - 安装部署到目标目录"
	@echo "                                    支持参数:"
	@echo "                                      GAME_DIR=项目名 (默认: LieRen，可通过命令行覆盖)"
	@echo "                                      BUILD_TYPE=构建类型 (可选，自动判断或默认: DynamicDebug)"
	@echo "                                        可选值: Debug/Release/DynamicDebug/DynamicRelease"
	@echo "                                        如果未指定，会自动检测最近构建的类型"
	@echo "                                        如果未检测到，默认使用 DynamicDebug 并先执行构建"
	@echo "                                      INSTALL_DIR=目标目录 (可选，默认: Deploy)"
	@echo "                                    示例: make install GAME_DIR=LieRen BUILD_TYPE=DynamicRelease INSTALL_DIR=/opt/game"
	@echo "                                    注意: 如果 BUILD_TYPE 未指定且未检测到已构建版本，"
	@echo "                                          会自动先执行构建，然后安装"
	@echo ""
	@echo "辅助目标:"
	@echo "  make clean-comm-makefiles   - 清理NFComm makefiles构建产物"
	@echo "  make clean-server-makefiles - 清理NFServerComm makefiles构建产物"
	@echo "  make clean-game             - 清理game构建目录（包含makefiles清理）"
	@echo "  make clean-debug            - 清理debug构建目录"
	@echo "  make clean-release          - 清理release构建目录"
	@echo "  make clean-dynamic-debug    - 清理dynamic-debug构建目录"
	@echo "  make clean-dynamic-release  - 清理dynamic-release构建目录"
	@echo "  make clean-protobuf         - 清理protobuf构建临时文件"
	@echo "  make clean-all              - 清理所有构建目录"
	@echo "  make prepare-dirs           - 创建必要的构建目录"
	@echo ""
	@echo "============================================================================"

# ============================================================================
# 目录准备
# ============================================================================
.PHONY: prepare-dirs
prepare-dirs:
	@echo "创建构建目录..."
	@mkdir -p $(BUILD_DIR)
	@mkdir -p $(BUILD_GAME_DIR)
	@mkdir -p $(BUILD_LIB_DIR)
	@mkdir -p $(BUILD_DEBUG_DIR)
	@mkdir -p $(BUILD_RELEASE_DIR)
	@mkdir -p $(BUILD_DYNAMIC_DEBUG_DIR)
	@mkdir -p $(BUILD_DYNAMIC_RELEASE_DIR)

# ============================================================================
# 环境准备（已移到 ci/build.sh init）
# ============================================================================
# 所有环境安装目标已移除，请使用: ./ci/build.sh init

# ============================================================================
# 清理目标
# ============================================================================
.PHONY: clean-comm-makefiles
clean-comm-makefiles:
	@echo "清理NFComm makefiles构建产物..."
	@cd $(NFCOMM_MAKEFILES) && $(MAKE) clean 2>/dev/null || true

.PHONY: clean-server-makefiles
clean-server-makefiles:
	@echo "清理NFServerComm makefiles构建产物..."
	@cd $(NFSERVER_MAKEFILES) && $(MAKE) clean 2>/dev/null || true

.PHONY: clean-game
clean-game: clean-comm-makefiles clean-server-makefiles
	@echo "清理game构建目录..."
	@rm -rf $(BUILD_GAME_DIR)/*
	@mkdir -p $(BUILD_GAME_DIR)

.PHONY: clean-debug
clean-debug:
	@echo "清理debug构建目录..."
	@if [ -d "$(BUILD_DEBUG_DIR)" ] && [ -f "$(BUILD_DEBUG_DIR)/CMakeCache.txt" ]; then \
		echo "执行 clean 清理编译输出（包括 Install 目录）..."; \
		cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) clean 2>/dev/null || true; \
		echo "清理 CMake 配置文件..."; \
		rm -rf $(BUILD_DEBUG_DIR)/* 2>/dev/null || true; \
	elif [ -d "$(BUILD_DEBUG_DIR)" ]; then \
		echo "构建目录存在但未配置，直接删除..."; \
		rm -rf $(BUILD_DEBUG_DIR)/* 2>/dev/null || true; \
	else \
		echo "构建目录不存在，无需清理"; \
	fi

.PHONY: clean-release
clean-release:
	@echo "清理release构建目录..."
	@if [ -d "$(BUILD_RELEASE_DIR)" ] && [ -f "$(BUILD_RELEASE_DIR)/CMakeCache.txt" ]; then \
		echo "执行 clean 清理编译输出（包括 Install 目录）..."; \
		cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) clean 2>/dev/null || true; \
		echo "清理 CMake 配置文件..."; \
		rm -rf $(BUILD_RELEASE_DIR)/* 2>/dev/null || true; \
	elif [ -d "$(BUILD_RELEASE_DIR)" ]; then \
		echo "构建目录存在但未配置，直接删除..."; \
		rm -rf $(BUILD_RELEASE_DIR)/* 2>/dev/null || true; \
	else \
		echo "构建目录不存在，无需清理"; \
	fi

.PHONY: clean-dynamic-debug
clean-dynamic-debug:
	@echo "清理dynamic-debug构建目录..."
	@if [ -d "$(BUILD_DYNAMIC_DEBUG_DIR)" ] && [ -f "$(BUILD_DYNAMIC_DEBUG_DIR)/CMakeCache.txt" ]; then \
		echo "执行 clean 清理编译输出（包括 Install 目录）..."; \
		cd $(BUILD_DYNAMIC_DEBUG_DIR) && $(BUILD_TOOL) clean 2>/dev/null || true; \
		echo "清理 CMake 配置文件..."; \
		rm -rf $(BUILD_DYNAMIC_DEBUG_DIR)/* 2>/dev/null || true; \
	elif [ -d "$(BUILD_DYNAMIC_DEBUG_DIR)" ]; then \
		echo "构建目录存在但未配置，直接删除..."; \
		rm -rf $(BUILD_DYNAMIC_DEBUG_DIR)/* 2>/dev/null || true; \
	else \
		echo "构建目录不存在，无需清理"; \
	fi

.PHONY: clean-dynamic-release
clean-dynamic-release:
	@echo "清理dynamic-release构建目录..."
	@if [ -d "$(BUILD_DYNAMIC_RELEASE_DIR)" ] && [ -f "$(BUILD_DYNAMIC_RELEASE_DIR)/CMakeCache.txt" ]; then \
		echo "执行 clean 清理编译输出（包括 Install 目录）..."; \
		cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) clean 2>/dev/null || true; \
		echo "清理 CMake 配置文件..."; \
		rm -rf $(BUILD_DYNAMIC_RELEASE_DIR)/* 2>/dev/null || true; \
	elif [ -d "$(BUILD_DYNAMIC_RELEASE_DIR)" ]; then \
		echo "构建目录存在但未配置，直接删除..."; \
		rm -rf $(BUILD_DYNAMIC_RELEASE_DIR)/* 2>/dev/null || true; \
	else \
		echo "构建目录不存在，无需清理"; \
	fi

.PHONY: clean-protobuf
clean-protobuf:
	@echo "清理protobuf构建临时文件..."
	@cd $(GOOGLE_PROTOBUF_PYTHON_DIR) && \
		$(PYTHON_CMD) setup.py clean --all 2>/dev/null || \
		(rm -rf build dist *.egg-info && echo "手动清理完成")
	@echo "[OK] protobuf构建文件清理完成"

.PHONY: clean-all
clean-all: clean-game clean-debug clean-release clean-dynamic-debug clean-dynamic-release
	@echo "清理完成"

# ============================================================================
# 子模块makefile执行
# ============================================================================
.PHONY: run-makefiles
run-makefiles:
ifeq ($(SKIP_MAKEFILES),1)
	@echo "跳过makefiles代码生成步骤 (SKIP_MAKEFILES=1)"
else
	@echo "执行子模块makefiles (GAME_DIR=$(GAME_DIR))..."
	cd $(NFCOMM_MAKEFILES) && $(MAKE)
	cd $(NFSERVER_MAKEFILES) && $(MAKE)
ifneq ($(GAME_DIR),)
	@echo "GAME_DIR已设置，执行game目录makefiles..."
	cd $(GAME_MAKEFILES) && $(MAKE) GAME_DIR=$(GAME_DIR)
else
	@echo "GAME_DIR为空，跳过game目录makefiles"
endif
endif

.PHONY: run-makefiles-patch
run-makefiles-patch:
ifeq ($(SKIP_MAKEFILES),1)
	@echo "跳过makefiles代码生成步骤 (SKIP_MAKEFILES=1)"
else
	@echo "执行子模块makefiles (GAME_DIR=$(GAME_DIR), 带版本补丁参数)..."
	cd $(NFCOMM_MAKEFILES) && $(MAKE) GAME_VERSION_PATCH=1
	cd $(NFSERVER_MAKEFILES) && $(MAKE) GAME_VERSION_PATCH=1
ifneq ($(GAME_DIR),)
	@echo "GAME_DIR已设置，执行game目录makefiles（patch模式）..."
	cd $(GAME_MAKEFILES) && $(MAKE) GAME_DIR=$(GAME_DIR) GAME_VERSION_PATCH=1
else
	@echo "GAME_DIR为空，跳过game目录makefiles"
endif
endif

# ============================================================================
# auto-make系列目标
# ============================================================================
.PHONY: auto-make
auto-make:
	@echo "执行auto-make..."
	@$(MAKE) run-makefiles

.PHONY: auto-make-all
auto-make-all:
	@echo "执行auto-make-all (清理后构建)..."
	@$(MAKE) prepare-dirs
	@$(MAKE) clean-game
	@$(MAKE) run-makefiles

.PHONY: auto-make-patch
auto-make-patch:
	@echo "执行auto-make-patch..."
	@$(MAKE) run-makefiles-patch

.PHONY: auto-make-patch-all
auto-make-patch-all:
	@echo "执行auto-make-patch-all (清理后构建)..."
	@$(MAKE) prepare-dirs
	@$(MAKE) clean-game
	@$(MAKE) run-makefiles-patch

# ============================================================================
# Debug构建目标
# ============================================================================
.PHONY: debug
debug:
	@echo "执行Debug构建..."
	@$(MAKE) prepare-dirs
	@$(MAKE) run-makefiles
	@echo "配置并构建Debug版本..."
	@if [ ! -f "$(BUILD_DEBUG_DIR)/CMakeCache.txt" ]; then \
		echo "首次构建，运行 CMake 配置..."; \
		echo "📋 CMake 命令:"; \
		echo "  cd $(BUILD_DEBUG_DIR) && \\"; \
		echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"; \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\";,) \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\";,) \
		echo "    ../.."; \
		if [ "$(DRY_RUN)" != "1" ]; then \
			cd $(BUILD_DEBUG_DIR) && \
			cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
			$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
			$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
			../.. && \
			$(BUILD_TOOL) -j$(JOBS); \
		else \
			echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
			echo "📋 构建命令: cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
			echo "🔍 [DRY-RUN] 跳过构建执行"; \
		fi; \
	else \
		echo "使用已有的 CMake 配置（增量构建）..."; \
		if [ -n "$(CMAKE_C_COMPILER_LAUNCHER)" ] && [ ! -f "$(CMAKE_C_COMPILER_LAUNCHER)" ]; then \
			echo "⚠️  Launcher 文件不存在，需要更新 CMake 配置"; \
			echo "📋 CMake 命令:"; \
			echo "  cd $(BUILD_DEBUG_DIR) && \\"; \
			echo "  cmake -Wno-dev \\"; \
			echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\"; \
			echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\"; \
			echo "    ../.."; \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_DEBUG_DIR) && \
				cmake -Wno-dev \
				-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)" \
				-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)" \
				../.. && \
				$(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
				echo "📋 构建命令: cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		else \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "📋 构建命令: cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		fi; \
	fi

.PHONY: debug-all
debug-all:
	@echo "执行Debug完整构建 (清理后构建)..."
	@$(MAKE) prepare-dirs
	@$(MAKE) clean-game
	@$(MAKE) run-makefiles
	@$(MAKE) clean-debug
	@echo "配置并构建Debug版本..."
	@echo "📋 CMake 命令:"
	@echo "  cd $(BUILD_DEBUG_DIR) && \\"
	@echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"
	$(if $(CMAKE_C_COMPILER_LAUNCHER),@echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\",)
	$(if $(CMAKE_CXX_COMPILER_LAUNCHER),@echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\",)
	@echo "    ../.."
	@if [ "$(DRY_RUN)" != "1" ]; then \
		cd $(BUILD_DEBUG_DIR) && \
		cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
		../.. && \
		$(BUILD_TOOL) -j$(JOBS); \
	else \
		echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
		echo "📋 构建命令: cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
		echo "🔍 [DRY-RUN] 跳过构建执行"; \
	fi

.PHONY: debug-patch
debug-patch:
	@echo "执行Debug补丁构建..."
	@$(MAKE) prepare-dirs
	@$(MAKE) run-makefiles-patch
	@echo "配置并构建Debug版本..."
	@if [ ! -f "$(BUILD_DEBUG_DIR)/CMakeCache.txt" ]; then \
		echo "首次构建，运行 CMake 配置..."; \
		echo "📋 CMake 命令:"; \
		echo "  cd $(BUILD_DEBUG_DIR) && \\"; \
		echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"; \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\";,) \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\";,) \
		echo "    ../.."; \
		if [ "$(DRY_RUN)" != "1" ]; then \
			cd $(BUILD_DEBUG_DIR) && \
			cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
			$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
			$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
			../.. && \
			$(BUILD_TOOL) -j$(JOBS); \
		else \
			echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
			echo "📋 构建命令: cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
			echo "🔍 [DRY-RUN] 跳过构建执行"; \
		fi; \
	else \
		echo "使用已有的 CMake 配置（增量构建）..."; \
		if [ -n "$(CMAKE_C_COMPILER_LAUNCHER)" ] && [ ! -f "$(CMAKE_C_COMPILER_LAUNCHER)" ]; then \
			echo "⚠️  Launcher 文件不存在，需要更新 CMake 配置"; \
			echo "📋 CMake 命令:"; \
			echo "  cd $(BUILD_DEBUG_DIR) && \\"; \
			echo "  cmake -Wno-dev \\"; \
			echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\"; \
			echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\"; \
			echo "    ../.."; \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_DEBUG_DIR) && \
				cmake -Wno-dev \
				-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)" \
				-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)" \
				../.. && \
				$(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
				echo "📋 构建命令: cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		else \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "📋 构建命令: cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		fi; \
	fi

.PHONY: debug-patch-all
debug-patch-all:
	@echo "执行Debug补丁完整构建 (清理后构建)..."
	@$(MAKE) prepare-dirs
	@$(MAKE) clean-game
	@$(MAKE) run-makefiles-patch
	@$(MAKE) clean-debug
	@echo "配置并构建Debug版本..."
	@echo "📋 CMake 命令:"
	@echo "  cd $(BUILD_DEBUG_DIR) && \\"
	@echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"
	$(if $(CMAKE_C_COMPILER_LAUNCHER),@echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\",)
	$(if $(CMAKE_CXX_COMPILER_LAUNCHER),@echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\",)
	@echo "    ../.."
	@if [ "$(DRY_RUN)" != "1" ]; then \
		cd $(BUILD_DEBUG_DIR) && \
		cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
		../.. && \
		$(BUILD_TOOL) -j$(JOBS); \
	else \
		echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
		echo "📋 构建命令: cd $(BUILD_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
		echo "🔍 [DRY-RUN] 跳过构建执行"; \
	fi

# ============================================================================
# DynamicDebug构建目标
# ============================================================================
.PHONY: dynamic-debug
dynamic-debug:
	@echo "执行DynamicDebug构建..."
	@$(MAKE) prepare-dirs
	@$(MAKE) run-makefiles
	@echo "配置并构建DynamicDebug版本..."
	@if [ ! -f "$(BUILD_DYNAMIC_DEBUG_DIR)/CMakeCache.txt" ]; then \
		echo "首次构建，运行 CMake 配置..."; \
		echo "📋 CMake 命令:"; \
		echo "  cd $(BUILD_DYNAMIC_DEBUG_DIR) && \\"; \
		echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicDebug -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"; \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\";,) \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\";,) \
		echo "    ../.."; \
		if [ "$(DRY_RUN)" != "1" ]; then \
			cd $(BUILD_DYNAMIC_DEBUG_DIR) && \
			cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicDebug -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
			$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
			$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
			../.. && \
			$(BUILD_TOOL) -j$(JOBS); \
		else \
			echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
			echo "📋 构建命令: cd $(BUILD_DYNAMIC_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
			echo "🔍 [DRY-RUN] 跳过构建执行"; \
		fi; \
	else \
		echo "使用已有的 CMake 配置（增量构建）..."; \
		if [ -n "$(CMAKE_C_COMPILER_LAUNCHER)" ] && [ ! -f "$(CMAKE_C_COMPILER_LAUNCHER)" ]; then \
			echo "⚠️  Launcher 文件不存在，需要更新 CMake 配置"; \
			echo "📋 CMake 命令:"; \
			echo "  cd $(BUILD_DYNAMIC_DEBUG_DIR) && \\"; \
			echo "  cmake -Wno-dev \\"; \
			echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\"; \
			echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\"; \
			echo "    ../.."; \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_DYNAMIC_DEBUG_DIR) && \
				cmake -Wno-dev \
				-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)" \
				-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)" \
				../.. && \
				$(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
				echo "📋 构建命令: cd $(BUILD_DYNAMIC_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		else \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_DYNAMIC_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "📋 构建命令: cd $(BUILD_DYNAMIC_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		fi; \
	fi

.PHONY: dynamic-debug-all
dynamic-debug-all:
	@echo "执行DynamicDebug完整构建 (清理后构建)..."
	@$(MAKE) prepare-dirs
	@$(MAKE) clean-game
	@$(MAKE) run-makefiles
	@$(MAKE) clean-dynamic-debug
	@echo "配置并构建DynamicDebug版本..."
	@echo "📋 CMake 命令:"
	@echo "  cd $(BUILD_DYNAMIC_DEBUG_DIR) && \\"
	@echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicDebug -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"
	$(if $(CMAKE_C_COMPILER_LAUNCHER),@echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\",)
	$(if $(CMAKE_CXX_COMPILER_LAUNCHER),@echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\",)
	@echo "    ../.."
	@if [ "$(DRY_RUN)" != "1" ]; then \
		cd $(BUILD_DYNAMIC_DEBUG_DIR) && \
		cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicDebug -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
		../.. && \
		$(BUILD_TOOL) -j$(JOBS); \
	else \
		echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
		echo "📋 构建命令: cd $(BUILD_DYNAMIC_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
		echo "🔍 [DRY-RUN] 跳过构建执行"; \
	fi

.PHONY: dynamic-debug-patch
dynamic-debug-patch:
	@echo "执行DynamicDebug补丁构建..."
	@$(MAKE) prepare-dirs
	@$(MAKE) run-makefiles-patch
	@echo "配置并构建DynamicDebug版本..."
	@if [ ! -f "$(BUILD_DYNAMIC_DEBUG_DIR)/CMakeCache.txt" ]; then \
		echo "首次构建，运行 CMake 配置..."; \
		cd $(BUILD_DYNAMIC_DEBUG_DIR) && \
		cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicDebug -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
		../.. && \
		$(BUILD_TOOL) -j$(JOBS); \
	else \
		echo "使用已有的 CMake 配置（增量构建）..."; \
		if [ -n "$(CMAKE_C_COMPILER_LAUNCHER)" ] && [ ! -f "$(CMAKE_C_COMPILER_LAUNCHER)" ]; then \
			echo "⚠️  Launcher 文件不存在，需要更新 CMake 配置"; \
			cd $(BUILD_DYNAMIC_DEBUG_DIR) && \
			cmake -Wno-dev \
			-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)" \
			-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)" \
			../.. && \
			$(BUILD_TOOL) -j$(JOBS); \
		else \
			cd $(BUILD_DYNAMIC_DEBUG_DIR) && $(BUILD_TOOL) -j$(JOBS); \
		fi; \
	fi

.PHONY: dynamic-debug-patch-all
dynamic-debug-patch-all:
	@echo "执行DynamicDebug补丁完整构建 (清理后构建)..."
	@$(MAKE) prepare-dirs
	@$(MAKE) clean-game
	@$(MAKE) run-makefiles-patch
	@$(MAKE) clean-dynamic-debug
	@echo "配置并构建DynamicDebug版本..."
	cd $(BUILD_DYNAMIC_DEBUG_DIR) && \
		cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicDebug -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
		../.. && \
		$(BUILD_TOOL) -j$(JOBS)

# ============================================================================
# DynamicRelease构建目标
# ============================================================================
.PHONY: dynamic-release
dynamic-release:
	@echo "执行DynamicRelease构建..."
	@mkdir -p $(BUILD_DIR)
	@mkdir -p $(BUILD_LIB_DIR)
	@mkdir -p $(BUILD_GAME_DIR)
	@mkdir -p $(BUILD_DYNAMIC_RELEASE_DIR)
	@$(MAKE) run-makefiles
	@echo "配置并构建DynamicRelease版本..."
	@if [ ! -f "$(BUILD_DYNAMIC_RELEASE_DIR)/CMakeCache.txt" ]; then \
		echo "首次构建，运行 CMake 配置..."; \
		echo "📋 CMake 命令:"; \
		echo "  cd $(BUILD_DYNAMIC_RELEASE_DIR) && \\"; \
		echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicRelease -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"; \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\";,) \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\";,) \
		echo "    ../.."; \
		if [ "$(DRY_RUN)" != "1" ]; then \
			cd $(BUILD_DYNAMIC_RELEASE_DIR) && \
			cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicRelease -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
			$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
			$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
			../.. && \
			$(BUILD_TOOL) -j$(JOBS); \
		else \
			echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
			echo "📋 构建命令: cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
			echo "🔍 [DRY-RUN] 跳过构建执行"; \
		fi; \
	else \
		echo "使用已有的 CMake 配置（增量构建）..."; \
		if [ -n "$(CMAKE_C_COMPILER_LAUNCHER)" ] && [ ! -f "$(CMAKE_C_COMPILER_LAUNCHER)" ]; then \
			echo "⚠️  Launcher 文件不存在，需要更新 CMake 配置"; \
			echo "📋 CMake 命令:"; \
			echo "  cd $(BUILD_DYNAMIC_RELEASE_DIR) && \\"; \
			echo "  cmake -Wno-dev \\"; \
			echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\"; \
			echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\"; \
			echo "    ../.."; \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_DYNAMIC_RELEASE_DIR) && \
				cmake -Wno-dev \
				-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)" \
				-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)" \
				../.. && \
				$(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
				echo "📋 构建命令: cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		else \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "📋 构建命令: cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		fi; \
	fi

.PHONY: dynamic-release-all
dynamic-release-all:
	@echo "执行DynamicRelease完整构建 (清理后构建)..."
	@$(MAKE) prepare-dirs
	@$(MAKE) clean-game
	@$(MAKE) run-makefiles
	@$(MAKE) clean-dynamic-release
	@echo "配置并构建DynamicRelease版本..."
	@echo "📋 CMake 命令:"
	@echo "  cd $(BUILD_DYNAMIC_RELEASE_DIR) && \\"
	@echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicRelease -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"
	$(if $(CMAKE_C_COMPILER_LAUNCHER),@echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\",)
	$(if $(CMAKE_CXX_COMPILER_LAUNCHER),@echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\",)
	@echo "    ../.."
	@if [ "$(DRY_RUN)" != "1" ]; then \
		cd $(BUILD_DYNAMIC_RELEASE_DIR) && \
		cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicRelease -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
		../.. && \
		$(BUILD_TOOL) -j$(JOBS); \
	else \
		echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
		echo "📋 构建命令: cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
		echo "🔍 [DRY-RUN] 跳过构建执行"; \
	fi

.PHONY: dynamic-release-patch
dynamic-release-patch:
	@echo "执行DynamicRelease补丁构建..."
	@mkdir -p $(BUILD_DIR)
	@mkdir -p $(BUILD_LIB_DIR)
	@mkdir -p $(BUILD_GAME_DIR)
	@mkdir -p $(BUILD_DYNAMIC_RELEASE_DIR)
	@$(MAKE) run-makefiles-patch
	@echo "配置并构建DynamicRelease版本..."
	@if [ ! -f "$(BUILD_DYNAMIC_RELEASE_DIR)/CMakeCache.txt" ]; then \
		echo "首次构建，运行 CMake 配置..."; \
		echo "📋 CMake 命令:"; \
		echo "  cd $(BUILD_DYNAMIC_RELEASE_DIR) && \\"; \
		echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicRelease -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"; \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\";,) \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\";,) \
		echo "    ../.."; \
		if [ "$(DRY_RUN)" != "1" ]; then \
			cd $(BUILD_DYNAMIC_RELEASE_DIR) && \
			cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicRelease -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
			$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
			$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
			../.. && \
			$(BUILD_TOOL) -j$(JOBS); \
		else \
			echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
			echo "📋 构建命令: cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
			echo "🔍 [DRY-RUN] 跳过构建执行"; \
		fi; \
	else \
		echo "使用已有的 CMake 配置（增量构建）..."; \
		if [ -n "$(CMAKE_C_COMPILER_LAUNCHER)" ] && [ ! -f "$(CMAKE_C_COMPILER_LAUNCHER)" ]; then \
			echo "⚠️  Launcher 文件不存在，需要更新 CMake 配置"; \
			echo "📋 CMake 命令:"; \
			echo "  cd $(BUILD_DYNAMIC_RELEASE_DIR) && \\"; \
			echo "  cmake -Wno-dev \\"; \
			echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\"; \
			echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\"; \
			echo "    ../.."; \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_DYNAMIC_RELEASE_DIR) && \
				cmake -Wno-dev \
				-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)" \
				-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)" \
				../.. && \
				$(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
				echo "📋 构建命令: cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		else \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "📋 构建命令: cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		fi; \
	fi

.PHONY: dynamic-release-patch-all
dynamic-release-patch-all:
	@echo "执行DynamicRelease补丁完整构建 (清理后构建)..."
	@$(MAKE) prepare-dirs
	@$(MAKE) clean-game
	@$(MAKE) run-makefiles-patch
	@$(MAKE) clean-dynamic-release
	@echo "配置并构建DynamicRelease版本..."
	@echo "📋 CMake 命令:"
	@echo "  cd $(BUILD_DYNAMIC_RELEASE_DIR) && \\"
	@echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicRelease -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"
	$(if $(CMAKE_C_COMPILER_LAUNCHER),@echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\",)
	$(if $(CMAKE_CXX_COMPILER_LAUNCHER),@echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\",)
	@echo "    ../.."
	@if [ "$(DRY_RUN)" != "1" ]; then \
		cd $(BUILD_DYNAMIC_RELEASE_DIR) && \
		cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicRelease -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
		../.. && \
		$(BUILD_TOOL) -j$(JOBS); \
	else \
		echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
		echo "📋 构建命令: cd $(BUILD_DYNAMIC_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
		echo "🔍 [DRY-RUN] 跳过构建执行"; \
	fi

# ============================================================================
# Release构建目标
# ============================================================================
.PHONY: release
release:
	@echo "执行Release构建..."
	@$(MAKE) prepare-dirs
	@$(MAKE) run-makefiles
	@echo "配置并构建Release版本..."
	@if [ ! -f "$(BUILD_RELEASE_DIR)/CMakeCache.txt" ]; then \
		echo "首次构建，运行 CMake 配置..."; \
		echo "📋 CMake 命令:"; \
		echo "  cd $(BUILD_RELEASE_DIR) && \\"; \
		echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"; \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\";,) \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\";,) \
		echo "    ../.."; \
		if [ "$(DRY_RUN)" != "1" ]; then \
			cd $(BUILD_RELEASE_DIR) && \
			cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
			$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
			$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
			../.. && \
			$(BUILD_TOOL) -j$(JOBS); \
		else \
			echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
			echo "📋 构建命令: cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
			echo "🔍 [DRY-RUN] 跳过构建执行"; \
		fi; \
	else \
		echo "使用已有的 CMake 配置（增量构建）..."; \
		if [ -n "$(CMAKE_C_COMPILER_LAUNCHER)" ] && [ ! -f "$(CMAKE_C_COMPILER_LAUNCHER)" ]; then \
			echo "⚠️  Launcher 文件不存在，需要更新 CMake 配置"; \
			echo "📋 CMake 命令:"; \
			echo "  cd $(BUILD_RELEASE_DIR) && \\"; \
			echo "  cmake -Wno-dev \\"; \
			echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\"; \
			echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\"; \
			echo "    ../.."; \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_RELEASE_DIR) && \
				cmake -Wno-dev \
				-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)" \
				-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)" \
				../.. && \
				$(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
				echo "📋 构建命令: cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		else \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "📋 构建命令: cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		fi; \
	fi

.PHONY: release-all
release-all:
	@echo "执行Release完整构建 (清理后构建)..."
	@$(MAKE) prepare-dirs
	@$(MAKE) clean-game
	@$(MAKE) run-makefiles
	@$(MAKE) clean-release
	@echo "配置并构建Release版本..."
	@echo "📋 CMake 命令:"
	@echo "  cd $(BUILD_RELEASE_DIR) && \\"
	@echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"
	$(if $(CMAKE_C_COMPILER_LAUNCHER),@echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\",)
	$(if $(CMAKE_CXX_COMPILER_LAUNCHER),@echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\",)
	@echo "    ../.."
	@if [ "$(DRY_RUN)" != "1" ]; then \
		cd $(BUILD_RELEASE_DIR) && \
		cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
		../.. && \
		$(BUILD_TOOL) -j$(JOBS); \
	else \
		echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
		echo "📋 构建命令: cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
		echo "🔍 [DRY-RUN] 跳过构建执行"; \
	fi

.PHONY: release-patch
release-patch:
	@echo "执行Release补丁构建..."
	@$(MAKE) prepare-dirs
	@$(MAKE) run-makefiles-patch
	@echo "配置并构建Release版本..."
	@if [ ! -f "$(BUILD_RELEASE_DIR)/CMakeCache.txt" ]; then \
		echo "首次构建，运行 CMake 配置..."; \
		echo "📋 CMake 命令:"; \
		echo "  cd $(BUILD_RELEASE_DIR) && \\"; \
		echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"; \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\";,) \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\";,) \
		echo "    ../.."; \
		if [ "$(DRY_RUN)" != "1" ]; then \
			cd $(BUILD_RELEASE_DIR) && \
			cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
			$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
			$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
			../.. && \
			$(BUILD_TOOL) -j$(JOBS); \
		else \
			echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
			echo "📋 构建命令: cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
			echo "🔍 [DRY-RUN] 跳过构建执行"; \
		fi; \
	else \
		echo "使用已有的 CMake 配置（增量构建）..."; \
		if [ -n "$(CMAKE_C_COMPILER_LAUNCHER)" ] && [ ! -f "$(CMAKE_C_COMPILER_LAUNCHER)" ]; then \
			echo "⚠️  Launcher 文件不存在，需要更新 CMake 配置"; \
			echo "📋 CMake 命令:"; \
			echo "  cd $(BUILD_RELEASE_DIR) && \\"; \
			echo "  cmake -Wno-dev \\"; \
			echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\"; \
			echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\"; \
			echo "    ../.."; \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_RELEASE_DIR) && \
				cmake -Wno-dev \
				-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)" \
				-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)" \
				../.. && \
				$(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
				echo "📋 构建命令: cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		else \
			if [ "$(DRY_RUN)" != "1" ]; then \
				cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS); \
			else \
				echo "📋 构建命令: cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
				echo "🔍 [DRY-RUN] 跳过构建执行"; \
			fi; \
		fi; \
	fi

.PHONY: release-patch-all
release-patch-all:
	@echo "执行Release补丁完整构建 (清理后构建)..."
	@$(MAKE) prepare-dirs
	@$(MAKE) clean-game
	@$(MAKE) run-makefiles-patch
	@$(MAKE) clean-release
	@echo "配置并构建Release版本..."
	@echo "📋 CMake 命令:"
	@echo "  cd $(BUILD_RELEASE_DIR) && \\"
	@echo "  cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_GAME:STRING=\"$(GAME_DIR)\" \\"
	$(if $(CMAKE_C_COMPILER_LAUNCHER),@echo "    -DCMAKE_C_COMPILER_LAUNCHER=\"$(CMAKE_C_COMPILER_LAUNCHER)\" \\",)
	$(if $(CMAKE_CXX_COMPILER_LAUNCHER),@echo "    -DCMAKE_CXX_COMPILER_LAUNCHER=\"$(CMAKE_CXX_COMPILER_LAUNCHER)\" \\",)
	@echo "    ../.."
	@if [ "$(DRY_RUN)" != "1" ]; then \
		cd $(BUILD_RELEASE_DIR) && \
		cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_GAME:STRING="$(GAME_DIR)" \
		$(if $(CMAKE_C_COMPILER_LAUNCHER),-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_C_COMPILER_LAUNCHER)") \
		$(if $(CMAKE_CXX_COMPILER_LAUNCHER),-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_CXX_COMPILER_LAUNCHER)") \
		../.. && \
		$(BUILD_TOOL) -j$(JOBS); \
	else \
		echo "🔍 [DRY-RUN] 跳过 CMake 配置执行"; \
		echo "📋 构建命令: cd $(BUILD_RELEASE_DIR) && $(BUILD_TOOL) -j$(JOBS)"; \
		echo "🔍 [DRY-RUN] 跳过构建执行"; \
	fi

# ============================================================================
# 工具构建目标
# ============================================================================
.PHONY: excelprocess
excelprocess:
	@echo "构建Excel处理工具..."
	@mkdir -p Build_excelprocess/build64_debug
	@rm -rf $(BUILD_EXCELPROCESS_DIR)/*
	cd $(BUILD_EXCELPROCESS_DIR) && \
		cmake -Wno-dev $(CMAKE_GENERATOR) -DCMAKE_BUILD_TYPE=DynamicRelease -DCMAKE_BUILD_TOOLS:BOOL=True ../.. && \
		$(BUILD_TOOL) -j16

# ============================================================================
# 兼容旧命名（可选保留一段时间后删除）
# ============================================================================
.PHONY: build-debug build-release build-dynamic-debug build-dynamic-release build-excelprocess
build-debug: debug
build-release: release
build-dynamic-debug: dynamic-debug
build-dynamic-release: dynamic-release
build-excelprocess: excelprocess

# ============================================================================
# 全部构建目标
# ============================================================================
.PHONY: all
all: debug-all

# ============================================================================
# 安装部署目标
# ============================================================================
# 辅助函数：根据 BUILD_TYPE 执行对应的构建目标
# 注意：此目标需要 BUILD_TYPE 参数，由 install 目标确保传入
.PHONY: build-for-install
build-for-install:
	@if [ -z "$(BUILD_TYPE)" ]; then \
		echo "错误: build-for-install 需要 BUILD_TYPE 参数"; \
		exit 1; \
	fi
	@echo "使用指定的构建类型: $(BUILD_TYPE)"
	@case "$(BUILD_TYPE)" in \
		Debug) \
			echo "执行 Debug 构建..."; \
			$(MAKE) debug GAME_DIR=$(GAME_DIR); \
			;; \
		Release) \
			echo "执行 Release 构建..."; \
			$(MAKE) release GAME_DIR=$(GAME_DIR); \
			;; \
		DynamicDebug) \
			echo "执行 DynamicDebug 构建..."; \
			$(MAKE) dynamic-debug GAME_DIR=$(GAME_DIR); \
			;; \
		DynamicRelease) \
			echo "执行 DynamicRelease 构建..."; \
			$(MAKE) dynamic-release GAME_DIR=$(GAME_DIR); \
			;; \
		*) \
			echo "错误: 未知的构建类型: $(BUILD_TYPE)"; \
			echo "支持的构建类型: Debug, Release, DynamicDebug, DynamicRelease"; \
			exit 1; \
			;; \
	esac

# ============================================================================
# 便捷安装目标：先编译后安装
# ============================================================================
# 这些目标会先执行对应的构建，然后执行安装
# 使用方式: make install-debug 或 make install-release
# ============================================================================
.PHONY: install-debug
install-debug:
	@echo "============================================================================"
	@echo "执行 Debug 构建并安装..."
	@echo "游戏项目: GAME_DIR = $(GAME_DIR)"
	@echo "============================================================================"
	@$(MAKE) debug GAME_DIR=$(GAME_DIR) && \
	$(MAKE) do-install BUILD_TYPE=Debug GAME_DIR=$(GAME_DIR) INSTALL_DIR=$(INSTALL_DIR)

.PHONY: install-release
install-release:
	@echo "============================================================================"
	@echo "执行 Release 构建并安装..."
	@echo "游戏项目: GAME_DIR = $(GAME_DIR)"
	@echo "============================================================================"
	@$(MAKE) release GAME_DIR=$(GAME_DIR) && \
	$(MAKE) do-install BUILD_TYPE=Release GAME_DIR=$(GAME_DIR) INSTALL_DIR=$(INSTALL_DIR)

.PHONY: install-dynamic-debug
install-dynamic-debug:
	@echo "============================================================================"
	@echo "执行 DynamicDebug 构建并安装..."
	@echo "游戏项目: GAME_DIR = $(GAME_DIR)"
	@echo "============================================================================"
	@$(MAKE) dynamic-debug GAME_DIR=$(GAME_DIR) && \
	$(MAKE) do-install BUILD_TYPE=DynamicDebug GAME_DIR=$(GAME_DIR) INSTALL_DIR=$(INSTALL_DIR)

.PHONY: install-dynamic-release
install-dynamic-release:
	@echo "============================================================================"
	@echo "执行 DynamicRelease 构建并安装..."
	@echo "游戏项目: GAME_DIR = $(GAME_DIR)"
	@echo "============================================================================"
	@$(MAKE) dynamic-release GAME_DIR=$(GAME_DIR) && \
	$(MAKE) do-install BUILD_TYPE=DynamicRelease GAME_DIR=$(GAME_DIR) INSTALL_DIR=$(INSTALL_DIR)

.PHONY: install
install:
ifeq ($(GAME_DIR),)
	@echo "============================================================================"
	@echo "错误: GAME_DIR 参数为空！"
	@echo "请指定游戏项目，例如: make install GAME_DIR=LieRen"
	@echo "============================================================================"
	@exit 1
else
	# 自动判断或使用 BUILD_TYPE
	@if [ -z "$(BUILD_TYPE)" ]; then \
		# 自动检测最近构建的类型（通过检查构建目录的 CMakeCache.txt） \
		BUILD_TYPE_DETECTED=""; \
		if [ -f "$(BUILD_DYNAMIC_DEBUG_DIR)/CMakeCache.txt" ]; then \
			BUILD_TYPE_DETECTED="DynamicDebug"; \
		elif [ -f "$(BUILD_DYNAMIC_RELEASE_DIR)/CMakeCache.txt" ]; then \
			BUILD_TYPE_DETECTED="DynamicRelease"; \
		elif [ -f "$(BUILD_DEBUG_DIR)/CMakeCache.txt" ]; then \
			BUILD_TYPE_DETECTED="Debug"; \
		elif [ -f "$(BUILD_RELEASE_DIR)/CMakeCache.txt" ]; then \
			BUILD_TYPE_DETECTED="Release"; \
		fi; \
		if [ -n "$$BUILD_TYPE_DETECTED" ]; then \
			echo "自动检测到构建类型: $$BUILD_TYPE_DETECTED"; \
			echo "将先执行 $$BUILD_TYPE_DETECTED 构建，然后安装..."; \
			$(MAKE) build-for-install BUILD_TYPE="$$BUILD_TYPE_DETECTED" GAME_DIR=$(GAME_DIR) && \
			$(MAKE) do-install BUILD_TYPE="$$BUILD_TYPE_DETECTED" GAME_DIR=$(GAME_DIR) INSTALL_DIR=$(INSTALL_DIR); \
		else \
			echo "未检测到已构建的版本，使用默认构建类型: DynamicDebug"; \
			echo "将先执行 DynamicDebug 构建，然后安装..."; \
			$(MAKE) build-for-install BUILD_TYPE=DynamicDebug GAME_DIR=$(GAME_DIR) && \
			$(MAKE) do-install BUILD_TYPE=DynamicDebug GAME_DIR=$(GAME_DIR) INSTALL_DIR=$(INSTALL_DIR); \
		fi; \
	else \
		# BUILD_TYPE 已指定，先构建后安装 \
		echo "使用指定的构建类型: $(BUILD_TYPE)"; \
		$(MAKE) build-for-install BUILD_TYPE=$(BUILD_TYPE) GAME_DIR=$(GAME_DIR) && \
		$(MAKE) do-install BUILD_TYPE=$(BUILD_TYPE) GAME_DIR=$(GAME_DIR) INSTALL_DIR=$(INSTALL_DIR); \
	fi
endif

# 实际执行安装的目标（内部使用）
.PHONY: do-install
do-install:
	@echo "============================================================================"
	@echo "开始安装部署..."
	@echo "游戏项目: GAME_DIR = $(GAME_DIR)"
	@echo "构建类型: BUILD_TYPE = $(BUILD_TYPE)"
	@echo "目标目录: INSTALL_DIR = $(INSTALL_DIR)"
	@echo "============================================================================"
	
	# 创建目标目录结构
	@echo ""
	@echo "创建目标目录结构..."
	@mkdir -p "$(INSTALL_DIR)/Bin/$(BUILD_TYPE)"
	@mkdir -p "$(INSTALL_DIR)/Config/$(GAME_DIR)"
	@mkdir -p "$(INSTALL_DIR)/Plugin/$(GAME_DIR)"
	@mkdir -p "$(INSTALL_DIR)/LuaScript/$(GAME_DIR)"
	
	# Windows 下直接复制所有二进制文件（包括 .exe 和 .dll）
	# Linux/macOS 下只复制非二进制文件（.exe 由 cmake install 处理）
ifeq ($(OS),Windows_NT)
	@echo ""
	@echo "Windows 环境：复制所有文件（包括 .exe 和 .dll）..."
	@if [ -d "Install/Bin/$(BUILD_TYPE)" ]; then \
		INSTALL_DIR_ABS="$$(cd "$(INSTALL_DIR)" 2>/dev/null && pwd || echo "$(CURDIR)/$(INSTALL_DIR)")"; \
		DEST_DIR_ABS="$$INSTALL_DIR_ABS/Bin/$(BUILD_TYPE)"; \
		echo "  从 Install/Bin/$(BUILD_TYPE) 复制所有文件到 $$DEST_DIR_ABS/"; \
		mkdir -p "$$DEST_DIR_ABS" || true; \
		cd Install/Bin/$(BUILD_TYPE) && \
		for file in *; do \
			[ "$$file" = "*" ] && continue; \
			if [ -f "$$file" ]; then \
				echo "    复制文件: $$file"; \
				cp "$$file" "$$DEST_DIR_ABS/" 2>&1 || echo "      警告: 复制失败: $$file"; \
			elif [ -d "$$file" ]; then \
				echo "    复制目录: $$file"; \
				cp -r "$$file" "$$DEST_DIR_ABS/" 2>&1 || echo "      警告: 复制目录失败: $$file"; \
			fi; \
		done || true; \
	else \
		echo "  警告: Install/Bin/$(BUILD_TYPE) 目录不存在，跳过"; \
	fi
else
	@echo ""
	@echo "Linux/macOS 环境：复制非二进制文件..."
	@if [ -d "Install/Bin/$(BUILD_TYPE)" ]; then \
		INSTALL_DIR_ABS="$$(cd "$(INSTALL_DIR)" 2>/dev/null && pwd || echo "$(CURDIR)/$(INSTALL_DIR)")"; \
		DEST_DIR_ABS="$$INSTALL_DIR_ABS/Bin/$(BUILD_TYPE)"; \
		echo "  从 Install/Bin/$(BUILD_TYPE) 复制非二进制文件到 $$DEST_DIR_ABS/"; \
		mkdir -p "$$DEST_DIR_ABS" || true; \
		cd Install/Bin/$(BUILD_TYPE) && \
		for file in *; do \
			[ "$$file" = "*" ] && continue; \
			if [ -f "$$file" ]; then \
				case "$$file" in \
					*.so|*.so.*|*.dll|*.dylib) \
						;; \
					*.exe) \
						;; \
					*) \
						IS_BINARY=0; \
						if command -v file >/dev/null 2>&1; then \
							if file "$$file" 2>/dev/null | grep -qE "(ELF.*executable|Mach-O.*executable|PE32.*executable)"; then \
								IS_BINARY=1; \
							fi; \
						fi; \
						if [ "$$IS_BINARY" != "1" ]; then \
							echo "    复制文件: $$file"; \
							cp "$$file" "$$DEST_DIR_ABS/" 2>&1 || echo "      警告: 复制失败: $$file"; \
						fi; \
						;; \
				esac; \
			elif [ -d "$$file" ]; then \
				echo "    复制目录: $$file"; \
				cp -r "$$file" "$$DEST_DIR_ABS/" 2>&1 || echo "      警告: 复制目录失败: $$file"; \
			fi; \
		done || true; \
	else \
		echo "  警告: Install/Bin/$(BUILD_TYPE) 目录不存在，跳过"; \
	fi
endif
	
	# Windows 下跳过 cmake install（已经通过直接复制完成）
	# Linux/macOS 下执行 cmake install
ifeq ($(OS),Windows_NT)
	@echo ""
	@echo "Windows 环境：跳过 cmake install（二进制文件已通过直接复制）"
else
	# 根据 BUILD_TYPE 确定构建目录并执行 cmake install
	@echo ""
	@echo "Linux/macOS 环境：执行 cmake install..."
	@BUILD_DIR=""; \
	case "$(BUILD_TYPE)" in \
		Debug) \
			BUILD_DIR="$(BUILD_DEBUG_DIR)"; \
			;; \
		Release) \
			BUILD_DIR="$(BUILD_RELEASE_DIR)"; \
			;; \
		DynamicDebug) \
			BUILD_DIR="$(BUILD_DYNAMIC_DEBUG_DIR)"; \
			;; \
		DynamicRelease) \
			BUILD_DIR="$(BUILD_DYNAMIC_RELEASE_DIR)"; \
			;; \
		*) \
			echo "  错误: 未知的构建类型: $(BUILD_TYPE)"; \
			exit 1; \
			;; \
	esac; \
	if [ -f "$$BUILD_DIR/CMakeCache.txt" ]; then \
		echo "  构建目录: $$BUILD_DIR"; \
		echo "  安装目录: $(INSTALL_DIR)"; \
		if cmake --install $$BUILD_DIR --prefix $(INSTALL_DIR) 2>/dev/null; then \
			echo "  cmake --install 执行成功"; \
		elif (cd $$BUILD_DIR && cmake --install . --prefix $(INSTALL_DIR) 2>/dev/null); then \
			echo "  cmake --install (从构建目录) 执行成功"; \
		else \
			echo "  警告: cmake --install 命令不可用（需要 CMake 3.15+），尝试使用 $(BUILD_TOOL) install"; \
			echo "  注意: 将使用构建目录中配置的 CMAKE_INSTALL_PREFIX，而不是 $(INSTALL_DIR)"; \
			echo "  提示: 如需指定安装目录，请使用: cd $$BUILD_DIR && cmake -DCMAKE_INSTALL_PREFIX=$(INSTALL_DIR) . && $(BUILD_TOOL) install"; \
			(cd $$BUILD_DIR && $(BUILD_TOOL) install 2>/dev/null) || \
			(cd $$BUILD_DIR && make install 2>/dev/null) || \
			echo "  错误: 安装失败"; \
		fi; \
	else \
		echo "  警告: $$BUILD_DIR/CMakeCache.txt 不存在，跳过 cmake install"; \
		echo "  提示: 请先执行构建命令，例如: make $(BUILD_TYPE) GAME_DIR=$(GAME_DIR)"; \
	fi
endif
	
	# 复制配置文件
	@echo ""
	@echo "复制配置文件..."
	@if [ -d "Install/Config/$(GAME_DIR)" ]; then \
		echo "  从 Install/Config/$(GAME_DIR) 复制到 $(INSTALL_DIR)/Config/$(GAME_DIR)/"; \
		cp -r Install/Config/$(GAME_DIR)/* "$(INSTALL_DIR)/Config/$(GAME_DIR)/" 2>/dev/null || true; \
	else \
		echo "  警告: Install/Config/$(GAME_DIR) 目录不存在，跳过"; \
	fi
	
	# 复制插件配置
	@echo ""
	@echo "复制插件配置..."
	@if [ -d "Install/Plugin/$(GAME_DIR)" ]; then \
		echo "  从 Install/Plugin/$(GAME_DIR) 复制到 $(INSTALL_DIR)/Plugin/$(GAME_DIR)/"; \
		cp -r Install/Plugin/$(GAME_DIR)/* "$(INSTALL_DIR)/Plugin/$(GAME_DIR)/" 2>/dev/null || true; \
	else \
		echo "  警告: Install/Plugin/$(GAME_DIR) 目录不存在，跳过"; \
	fi
	
	# 复制 Lua 脚本
	@echo ""
	@echo "复制 Lua 脚本..."
	@if [ -d "Install/LuaScript/$(GAME_DIR)" ]; then \
		echo "  从 Install/LuaScript/$(GAME_DIR) 复制到 $(INSTALL_DIR)/LuaScript/$(GAME_DIR)/"; \
		cp -r Install/LuaScript/$(GAME_DIR)/* "$(INSTALL_DIR)/LuaScript/$(GAME_DIR)/" 2>/dev/null || true; \
	else \
		echo "  警告: Install/LuaScript/$(GAME_DIR) 目录不存在，跳过"; \
	fi
	
	# 复制 NFServerController
	@echo ""
	@echo "复制 NFServerController..."
ifeq ($(OS),Windows_NT)
	@if [ -f "tools/NFServerController.exe" ]; then \
		echo "  从 tools/NFServerController.exe 复制到 $(INSTALL_DIR)/"; \
		cp tools/NFServerController.exe "$(INSTALL_DIR)/" 2>/dev/null || true; \
	else \
		echo "  警告: tools/NFServerController.exe 不存在，跳过"; \
	fi
else
	@if [ -f "tools/NFServerController" ]; then \
		echo "  从 tools/NFServerController 复制到 $(INSTALL_DIR)/"; \
		cp tools/NFServerController "$(INSTALL_DIR)/" 2>/dev/null || true; \
		chmod +x "$(INSTALL_DIR)/NFServerController" 2>/dev/null || true; \
	else \
		echo "  警告: tools/NFServerController 不存在，跳过"; \
	fi
endif
	
	# 复制 linux_servers.conf
	@echo ""
	@echo "复制 linux_servers.conf..."
	@if [ -f "Install/linux_servers.conf" ]; then \
		echo "  从 Install/linux_servers.conf 复制到 $(INSTALL_DIR)/"; \
		cp Install/linux_servers.conf "$(INSTALL_DIR)/" 2>/dev/null || true; \
	else \
		echo "  警告: Install/linux_servers.conf 不存在，跳过"; \
	fi
	

	@echo ""
	@echo "============================================================================"
	@echo "安装完成！"
	@echo "目标目录: $(INSTALL_DIR)"
	@echo ""
	@echo "目录结构:"
	@echo "  $(INSTALL_DIR)/NFServerController  - 服务器控制器"
	@echo "  $(INSTALL_DIR)/linux_servers.conf  - 服务器配置文件"
	@echo "  $(INSTALL_DIR)/Bin/$(BUILD_TYPE)/  - 可执行文件和动态库"
	@echo "  $(INSTALL_DIR)/Config/             - 配置文件"
	@echo "  $(INSTALL_DIR)/Plugin/             - 插件配置"
	@echo "  $(INSTALL_DIR)/LuaScript/          - Lua脚本"
	@echo ""
	@echo "启动服务器:"
ifeq ($(OS),Windows_NT)
	@echo "  cd $(INSTALL_DIR) && NFServerController.exe"
else
	@echo "  cd $(INSTALL_DIR) && ./NFServerController"
endif
	@echo "============================================================================"

# ============================================================================
# 注意事项
# ============================================================================
# 1. 🚀 首次使用前必须执行环境准备
#    ./ci/build.sh init
#    - 智能检测并安装 Python（优先 Python 3）
#    - 安装编译工具（gcc, g++, make, cmake, ninja, ccache）
#    - 配置分布式编译环境（distcc/icecc）
#    - 安装 setuptools 和 Protobuf Python 库
#    - 完全自动化，只需输入一次 sudo 密码
#    
# 2. 📖 使用指南
#    环境准备（只需一次）：
#      ./ci/build.sh init
#    
#    日常构建（不需要 sudo）：
#      ./build_dynamic_debug.sh          # 推荐：快捷脚本
#      或
#      make dynamic-debug GAME_DIR=LieRen
#      或
#      ./ci/build.sh dynamic-debug --game LieRen
#    
#    查看帮助：
#      make help
#
# 3. ⚙️  可选参数说明
#    - GAME_DIR：指定游戏项目目录
#      示例：make debug GAME_DIR=LieRen
#    
#    - SKIP_MAKEFILES：跳过代码生成步骤（proto/Excel未变化时）
#      示例：make debug SKIP_MAKEFILES=1
#      效果：大幅加快构建速度
#    
#    - JOBS：并行编译任务数
#      示例：make debug JOBS=8
#
# 4. 🎯 构建目标说明
#    - patch 系列：传递 GAME_VERSION_PATCH=1 参数给子 makefiles
#    - all 系列：构建前自动清理相关目录
#    - 多参数组合示例：make debug GAME_DIR=LieRen SKIP_MAKEFILES=1 JOBS=8
#
# 5. 🔧 故障排查
#    环境问题：
#    - 运行 ./ci/build.sh init 重新初始化
#    
#    编译问题：
#    - 检查 ci/build.sh 日志输出
#    - 查看 /tmp/distcc_*.log 分布式编译日志
#
# 6. 📝 重要变更
#    - Makefile 不再包含环境安装逻辑
#    - 所有环境准备已统一到 ci/build.sh init
#    - Makefile 专注于构建任务
# ============================================================================

